#include "utils.hpp"
#include "role.hpp"
#include <bits/stdc++.h>
using namespace std;

int main(int argc, char *argv[]) {
  int c;
  int is_client = -1, is_server = -1;
  int base_port_index = -1;
  int device_id = 0;
  int memcache_port = 0;
  char memcache_ip[64];
  int blk_size = 0;
  char test_mode[STR_LEN]={0};
  int num_qps = 1;
  long long iter_num = 10000LL;
  struct input_params *param_arr;

  static struct option opts[] = {
      {"iter", 1, NULL, 'i'},
      {"num-qps", 1, NULL, 'n'},
      {"blk-size", 1, NULL, 'a'},
      {"test-mode", 1, NULL, 't'},
      {"base-port-index", 1, NULL, 'b'},
      {"is-client", 1, NULL, 'C'},
      {"is-server", 1, NULL, 'S'},     
      {"device-id", 1, NULL, 'd'},
      {"memcached-server-ip", 1, NULL, 'X'},
      {"memcached-server-port", 1, NULL, 'P'},
      {NULL, 0, NULL, 0}};

  /* Parse and check arguments */
  while (1) {
    c = getopt_long(argc, argv, "i:h:n:b:C:S:d:L:X:P:", opts, NULL);
    if (c == -1) {
      break;
    }
    switch (c) {
    case 'i':
      iter_num = atoll(optarg);
      cout<<"iteration "<<iter_num<<endl;
      break;
    case 'a':
      blk_size = atoi(optarg);
      printf("block size is %d\n",blk_size);
      break;
    case 'n':
      num_qps = atoi(optarg);
      printf("qp num is %d\n",num_qps);
      break;
    case 't':
      strcpy(test_mode, optarg);
      break;
    case 'b':
      base_port_index = atoi(optarg);
      printf("port index: %d\n",base_port_index);
      break;
    case 'C':
      is_client = atoi(optarg);
      printf("this is client\n");
      break;
    case 'S':
      is_server = atoi(optarg);
      printf("this is server\n");
      break;
    case 'd':
      device_id = atoi(optarg);
      printf("device id: %d\n",device_id);
      break;
    case 'X':
      strcpy(memcache_ip,optarg);
      printf("memcached-server-ip = %s\n", memcache_ip);
      break;
    case 'P':
      memcache_port = atoi(optarg);
      printf("memcached-server-port = %d\n",memcache_port);
      break;
    default:
      printf("Invalid argument %c\n", c);
      assert(0);
    }
  }

  /* Common checks for all (master, workers, clients */
  assert(base_port_index >= 0 && base_port_index <= 8);

  /* Common sanity checks for worker process and per-machine client process */
  assert((is_client + is_server) == 0);

  assert(device_id >= 0);
  if(is_client > 0){
    assert(blk_size > 0);
    assert(num_qps > 0);
    assert(iter_num > 0);
  }

  printf("This is running as [%s]!\n",(is_client == 1) ? "CN" : "SR");

  param_arr = (input_params *)malloc(sizeof(input_params));

  {
    param_arr->base_port_index = base_port_index;
    param_arr->device_id = device_id;
    param_arr->blk_size = blk_size;
    strcpy(param_arr->test_mode, test_mode);
    strcpy(param_arr->memcache_ip,memcache_ip);
    param_arr->memcache_port = memcache_port;
    param_arr->num_qps = num_qps;
    param_arr->iter_num = iter_num;
    if (is_client >= 0)
      run_client(param_arr);
    if (is_server >= 0)
      run_server(param_arr);
  }
  return 0;
}
